#pragma once
#include <mutex>
#include <cassert>
#include "util.hpp"
#include "MysqlPool.hpp"
class user_table
{
public:
    // user_table(const std::string &host,
    //            const std::string &username,
    //            const std::string &password,
    //            const std::string &dbname,
    //            uint16_t port = 3306)
    // {
    //     _mysql = mysql_util::mysql_create(host, username, password, dbname, port);
    //     assert(_mysql != NULL);
    // }

    // ~user_table()
    // {
    //     mysql_util::mysql_destory(_mysql);
    //     _mysql = NULL;
    // }

    // 注册新增用户
    bool insert(Json::Value &user)
    {
#define INSERT_USER "insert into user values(null,'%s',MD5('%s'),1000,0,0);"
        if (user["username"].isNull() || user["password"].isNull())
        {
            DBG_LOG("INPUT PASSWORD OR USERNAME");
            return false;
        }
        char sql[4096] = {0};
        sprintf(sql, INSERT_USER, user["username"].asCString(), user["password"].asCString());
        std::unique_lock<std::mutex> lock(_mutex);
        MYSQL *mysql = MysqlPool::getInstance()->getConnection();
        bool ret = mysql_util::mysql_exec(mysql, sql);
        if (!ret)
        {
            DBG_LOG("insert user info failed!");
            MysqlPool::getInstance()->retConnection(mysql);
            return false;
        }
        MysqlPool::getInstance()->retConnection(mysql);
        return true;
    }

    // 登录验证,返回详细的用户信息
    bool login(Json::Value &user)
    {
        if (user["username"].isNull() || user["password"].isNull())
        {
            DBG_LOG("THERE is NO USER");
            return false;
        }
// 查询条件 用户名&&密码
#define LOGIN_USER "select id,username,score,total_count,win_count from user where username='%s' and password=MD5('%s');"
        char sql[4096] = {0};
        sprintf(sql, LOGIN_USER, user["username"].asCString(), user["password"].asCString());
        DBG_LOG("%s", sql);
        MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            MYSQL *mysql = MysqlPool::getInstance()->getConnection();
            bool ret = mysql_util::mysql_exec(mysql, sql);
            if (ret == false)
            {
                DBG_LOG("have no login user info!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            res = mysql_store_result(mysql);
            if(res == NULL)
            {
                DBG_LOG("get result failed! error: %s", mysql_error(mysql));
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            int row_num = mysql_num_rows(res);
            if (row_num != 1)
            {
                DBG_LOG("the user information queried is not unique!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            MYSQL_ROW row = mysql_fetch_row(res);
            user["id"] = (Json::UInt64)std::stoull(row[0]);
            user["username"] = row[1];
            user["score"] = (Json::Int)std::stoi(row[2]);
            user["total_count"] = std::stoi(row[3]);
            user["win_count"] = std::stoi(row[4]);
            mysql_free_result(res);
            MysqlPool::getInstance()->retConnection(mysql);
        }
        return true;
    }

    // 通过用户名获取用户信息
    bool select_by_name(const std::string &name, Json::Value &user)
    {
#define USER_BY_NAME "select id,username,score,total_count,win_count from user where username='%s';"
        char sql[4096] = {0};
        sprintf(sql, USER_BY_NAME, name.c_str());
        MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            MYSQL *mysql = MysqlPool::getInstance()->getConnection();
            bool ret = mysql_util::mysql_exec(mysql, sql);
            if (!ret)
            {
                DBG_LOG("have no login user info!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            // 要么有数据,要么无数据,有且只能有一条
            res = mysql_store_result(mysql);
            if (res == NULL)
            {
                DBG_LOG("have no user info!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            int row_num = mysql_num_rows(res);
            if (row_num != 1)
            {
                DBG_LOG("the user information queried is not unique!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            MYSQL_ROW row = mysql_fetch_row(res);
            user["id"] = (Json::UInt64)std::stoull(row[0]);
            user["username"] = row[1];
            user["score"] = (Json::Int)std::stoi(row[2]);
            user["total_count"] = std::stoi(row[3]);
            user["win_count"] = std::stoi(row[4]);
            mysql_free_result(res);
            MysqlPool::getInstance()->retConnection(mysql);
        }

        return true;
    }
    // 通过id查找
    bool select_by_id(uint64_t id, Json::Value &user)
    {
#define USER_BY_ID "select id,username,score,total_count,win_count from user where id=%lu;"
        char sql[4096] = {0};
        sprintf(sql, USER_BY_ID, id);
        MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            MYSQL *mysql = MysqlPool::getInstance()->getConnection();
            bool ret = mysql_util::mysql_exec(mysql, sql);
            if (!ret)
            {
                DBG_LOG("get user by id failed!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            // 要么有数据,要么无数据,有且只能有一条
            res = mysql_store_result(mysql);
            if (res == NULL)
            {
                DBG_LOG("have no user info!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            int row_num = mysql_num_rows(res);
            if (row_num != 1)
            {
                DBG_LOG("the user information queried is not unique!");
                MysqlPool::getInstance()->retConnection(mysql);
                return false;
            }
            MYSQL_ROW row = mysql_fetch_row(res);
            user["id"] = (Json::UInt64)std::stoull(row[0]);
            user["username"] = row[1];
            user["score"] = (Json::Int)std::stoi(row[2]);
            user["total_count"] = std::stoi(row[3]);
            user["win_count"] = std::stoi(row[4]);
            mysql_free_result(res);
            MysqlPool::getInstance()->retConnection(mysql);
        }
        return true;
    }

    // 胜利时天梯分数增加30,总战斗场次增加1,胜利场次加1
    bool win(uint64_t id)
    {
#define USER_WIN "update user set score=score+30,total_count=total_count+1,win_count=win_count+1 where id=%lu;"
        char sql[4096] = {0};
        sprintf(sql, USER_WIN, id);
        std::unique_lock<std::mutex> lock(_mutex);
        MYSQL *mysql = MysqlPool::getInstance()->getConnection();
        bool ret = mysql_util::mysql_exec(mysql, sql);
        if (!ret)
        {
            DBG_LOG("update win user info failed!");
            MysqlPool::getInstance()->retConnection(mysql);
            return false;
        }
        MysqlPool::getInstance()->retConnection(mysql);
        return true;
    }

    // 失败时天梯分减少30,总战斗场次加1,胜利场次不变
    bool lose(uint64_t id)
    {
#define USER_LOSE "update user set score=score-30,total_count=total_count+1 where id=%lu;"
        char sql[4096] = {0};
        sprintf(sql, USER_LOSE, id);
        std::unique_lock<std::mutex> lock(_mutex);
        MYSQL *mysql = MysqlPool::getInstance()->getConnection();
        bool ret = mysql_util::mysql_exec(mysql, sql);
        if (!ret)
        {
            DBG_LOG("update win user info failed!");
            MysqlPool::getInstance()->retConnection(mysql);
            return false;
        }
        MysqlPool::getInstance()->retConnection(mysql);
        return true;
    }

private:
    // MYSQL *_mysql;
    std::mutex _mutex; // 互斥锁保护数据库的访问操作
};